package repositories

import (
	"context"
	"github.com/pkg/errors"
	"go.didapinche.com/foundation/plat-echo/app/ops/models"
	"gorm.io/gorm"
)

type DingdingRepository interface {
	Create(ctx context.Context, Dingding *models.DingDing) (*models.DingDing, error)
	FindAll(ctx context.Context) ([]*models.DingDing, error)
	Update(ctx context.Context, Dingding *models.DingDing) (*models.DingDing, error)
	DeleteByID(ctx context.Context, ID uint64) error
	FindByLevelAndGroup(ctx context.Context, level int, groupName string) (*models.DingDing, error)
	FindByID(ctx context.Context, ID uint64) (*models.DingDing, error)
	Find(ctx context.Context, info *models.DingDing) ([]*models.DingDing, int64, error)
}

type dingdingRepository struct {
	db *gorm.DB
}

func NewDingdingRepository(db *gorm.DB) DingdingRepository {
	return &dingdingRepository{
		db: db,
	}
}

func (d *dingdingRepository) Create(ctx context.Context, Dingding *models.DingDing) (*models.DingDing, error) {
	if err := d.db.WithContext(ctx).Table(models.DingDingTableName).Create(Dingding).Error; err != nil {
		return nil, errors.Wrap(err, "create Dingding error")
	}
	return Dingding, nil
}

func (d *dingdingRepository) FindAll(ctx context.Context) (result []*models.DingDing, err error) {
	if err := d.db.WithContext(ctx).Table(models.DingDingTableName).Find(&result, "'type'=0").Error; err != nil {
		return nil, errors.Wrap(err, "find all Dingding error")
	}
	return result, nil
}

func (d *dingdingRepository) Update(ctx context.Context, Dingding *models.DingDing) (*models.DingDing, error) {
	if err := d.db.WithContext(ctx).Table(models.DingDingTableName).Save(Dingding).Error; err != nil {
		return nil, errors.Wrap(err, "update Dingding error")
	}
	return Dingding, nil
}

func (d *dingdingRepository) DeleteByID(ctx context.Context, ID uint64) error {
	if err := d.db.WithContext(ctx).Table(models.DingDingTableName).Delete(models.DingDing{}, "id = ?", ID).Error; err != nil {
		return errors.Wrap(err, "delete Dingding error")
	}
	return nil
}

func (d *dingdingRepository) FindByID(ctx context.Context, ID uint64) (*models.DingDing, error) {
	var Dingding = new(models.DingDing)
	if err := d.db.WithContext(ctx).Table(models.DingDingTableName).Where("id = ?", ID).First(&Dingding).Error; err != nil {
		return nil, errors.Wrap(err, "delete Dingding error")
	}
	return Dingding, nil
}

func (d *dingdingRepository) FindByLevelAndGroup(ctx context.Context, level int, groupName string) (*models.DingDing, error) {
	var Dingding = new(models.DingDing)
	if err := d.db.WithContext(ctx).Table(models.DingDingTableName).Where("level = ? and group_name=?", level, groupName).First(&Dingding).Error; err != gorm.ErrRecordNotFound && err != nil {
		return nil, errors.Wrap(err, "delete Dingding error")
	}
	return Dingding, nil
}

func (d *dingdingRepository) Find(ctx context.Context, info *models.DingDing) ([]*models.DingDing, int64, error) {
	result := make([]*models.DingDing, 0)
	totalCount := int64(0)

	q := d.db.WithContext(ctx).Table(models.DingDingTableName)

	if info.Name != "" {
		q = q.Where("name like ?", "%"+info.Name+"%")
	}

	if info.GroupID != "" {
		q = q.Where("group_id = ?", info.GroupID)
	}

	if info.GroupName != "" {
		q = q.Where("group_name = ?", info.GroupName)
	}

	if info.Level != 0 {
		q = q.Where("level = ?", info.Level)
	}

	if info.PageNum == 0 && info.PageSize == 0 {
		info.PageNum = 1
		info.PageSize = 1
	}

	if err := q.Order("t_ding_ding.create_time desc").
		Count(&totalCount).
		Limit(info.PageSize).
		Offset(info.PageSize * (info.PageNum - 1)).
		Scan(&result).
		Error; err != nil {
		return nil, 0, errors.Wrap(err, "find ding ding info error")
	}

	return result, totalCount, nil
}
